#ifndef CONTEXT_H_INCLUDED
#define CONTEXT_H_INCLUDED

#include <string>
#include <map>

#include "libxml/parser.h"

#include "sc/setup.h"

namespace sc {


/**
 * @class SetupContext
 *
 * This class represent the context of a xml file.
 */
class SetupContext
{
public:
    struct TMmiElement
    {
        std::string sValue;
        std::string sDefault;
        std::string sIcon;
    };
    typedef std::map<std::string, TMmiElement> TMmiElements;

    struct TMmiAttribute
    {
        std::string sValue;
        std::string sError;
        std::string sHelp;
    };
    typedef std::map<std::string, TMmiAttribute> TMmiAttributes;

protected:
    Setup       m_setup;

    std::string   m_sFileRNG;
    std::string   m_sFileXML;

    TMmiElements     m_MmiElements;
    TMmiAttributes   m_MmiAttributes;

    const std::string*  m_psFilename;

public:
	SetupContext(const std::string& sFilename)
	: m_psFilename(&sFilename)
	{
    }

	~SetupContext(void)
	{
	    Clear();
    }

private:
    SetupContext(const SetupContext& rcCtx);
    SetupContext& operator = (const SetupContext& rcCtx);

public:
    int Load(const xmlNodePtr pNodeFile);
    int Save(xmlTextWriterPtr xmlWriter) const;
    int SaveSetup(void) const;

    void Clear(void);

    Setup& GetSetup(void) { return m_setup; }
    const Setup& GetSetup(void) const { return m_setup; }

    const TMmiElements& GetMmiElements(void) const { return m_MmiElements; }
    std::string GetElementLabel(const setup::Element& rcElement) const;

    const TMmiAttributes& GetMmiAttributes(void) const { return m_MmiAttributes; }
    std::string GetAttributeLabel(const setup::Attribute& rcAttribute) const;
    std::string GetAttributeError(const setup::Attribute& rcAttribute) const;
    std::string GetAttributeHelp(const setup::Attribute& rcAttribute) const;

    bool SetConfigFile(const std::string& sFileRNG);
    const std::string& GetConfigFile(void) const { return m_sFileRNG; }

    bool SetXmlFile(const std::string& sFileXML, bool bRelative = true);
    const std::string& GetXmlFile(void) const { return m_sFileXML; }

protected:
    int LoadMMI(const xmlNodePtr pNodeMMI);
    int LoadElementLabel(const xmlNodePtr pNodeLabel);
    int LoadAttributeLabel(const xmlNodePtr pNodeLabel);

    int SaveConfig(xmlTextWriterPtr xmlWriter) const;
    int SaveSetup(xmlTextWriterPtr xmlWriter) const;
    int SaveMMI(xmlTextWriterPtr xmlWriter) const;
};

/**
 * @class Context
 *
 * This class represent the entire context, containing all xml file context.
 */
class Context
{
protected:
    typedef std::vector<SetupContext*> TSetupContexts;

    xmlDocPtr       m_sccDoc;
    std::string     m_sTitle;
    std::string     m_sFilename;
    TSetupContexts  m_setupContexts;

public:
    Context(void)
    : m_sccDoc(NULL)
    {
    }

    ~Context(void)
    {
        Clear();
    }

private:
    Context(const Context& rcCtx);
    Context& operator = (const Context& rcCtx);

public:
    void Clear(void);

    int Load(const std::string& sFilenameSCC);
    int Save(void);
    int SaveSetups(void) const;

    bool SetTitle(const std::string& sTitle);
    const std::string& GetTitle(void) const { return m_sTitle; }

    bool SetFile(const std::string& sFileSCC);
    const std::string& GetFile(void) const { return m_sFilename; }

    size_t GetSetupCount(void) const
    {
        return m_setupContexts.size();
    }

    SetupContext* GetSetupContext(size_t pos)
    {
        return pos >= m_setupContexts.size() ? NULL : m_setupContexts.at(pos);
    }

    const SetupContext* GetSetupContext(size_t pos) const
    {
        return pos >= m_setupContexts.size() ? NULL : m_setupContexts.at(pos);
    }

    std::string FileRelativeToContext(const std::string& sFile) const;
};

}; // namespace sc

#endif // CONTEXT_H_INCLUDED
